<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/ZendSkeletonApplication for the canonical source repository
 * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Crm;

use Zend\Mvc\ModuleRouteListener;
use Zend\Mvc\MvcEvent;
use Zend\Session\Container;
use Zend\Session\SessionManager;

use Zend\Authentication\AuthenticationService;
use Zend\Permissions\Acl\Acl;
use Zend\Permissions\Acl\Role\GenericRole as Role;
use Zend\Permissions\Acl\Resource\GenericResource as Resource;

class Module
{
    public function onBootstrap(MvcEvent $e)
    {
        $eventManager        = $e->getApplication()->getEventManager();
        $moduleRouteListener = new ModuleRouteListener();
        $moduleRouteListener->attach($eventManager);
        
        //session
        $this->bootstrapSession($e);
        
        $this->initAcl($e);
         
        
        $e->getApplication()->getEventManager()->attach(
            MvcEvent::EVENT_ROUTE, array($this, 'checkAcl')
            );
        
    }

    public function getConfig()
    {
        return include __DIR__ . '/config/module.config.php';
    }

    public function getAutoloaderConfig()
    {
        return array(
            'Zend\Loader\StandardAutoloader' => array(
                'namespaces' => array(
                    __NAMESPACE__ => __DIR__ . '/src/' . __NAMESPACE__,
                ),
            ),
        );
    }
    
    //session
    public function bootstrapSession($e)
    {
        $session = $e->getApplication()->getServiceManager()->get('Zend\Session\SessionManager');
        $session->start();
    
        $container = new Container('initialized');
        if (!isset($container->init)) {
            $serviceManager = $e->getApplication()->getServiceManager();
            $request        = $serviceManager->get('Request');
    
            $session->regenerateId(true);
            $container->init          = 1;
            $container->remoteAddr    = $request->getServer()->get('REMOTE_ADDR');
            $container->httpUserAgent = $request->getServer()->get('HTTP_USER_AGENT');
    
            $config = $serviceManager->get('Config');
            if (!isset($config['session'])) {
                return;
            }
    
            $sessionConfig = $config['session'];
            if (isset($sessionConfig['validators'])) {
                $chain   = $session->getValidatorChain();
    
                foreach ($sessionConfig['validators'] as $validator) {
                    switch ($validator) {
                        case 'Zend\Session\Validator\HttpUserAgent':
                            $validator = new $validator($container->httpUserAgent);
                            break;
                        case 'Zend\Session\Validator\RemoteAddr':
                            $validator  = new $validator($container->remoteAddr);
                            break;
                        default:
                            $validator = new $validator();
                    }
    
                    $chain->attach('session.validate', array($validator, 'isValid'));
                }
            }
        }
    }
    
    
    //session
    public function getServiceConfig()
    {
        return array(
            'factories' => array(
                'Zend\Session\SessionManager' => function ($sm) {
                    $config = $sm->get('config');
                    if (isset($config['session'])) {
                        $session = $config['session'];
        
                        $sessionConfig = null;
                        if (isset($session['config'])) {
                            $class = isset($session['config']['class'])  ? $session['config']['class'] : 'Zend\Session\Config\SessionConfig';
                            $options = isset($session['config']['options']) ? $session['config']['options'] : array();
                            $sessionConfig = new $class();
                            $sessionConfig->setOptions($options);
                        }
        
                        $sessionStorage = null;
                        if (isset($session['storage'])) {
                            $class = $session['storage'];
                            $sessionStorage = new $class();
                        }
        
                        $sessionSaveHandler = null;
                        if (isset($session['save_handler'])) {
                            // class should be fetched from service manager since it will require constructor arguments
                            $sessionSaveHandler = $sm->get($session['save_handler']);
                        }
        
                        $sessionManager = new SessionManager($sessionConfig, $sessionStorage, $sessionSaveHandler);
                    } else {
                        //$sessionManager = new SessionManager();
                        $sessionManager = new SessionManager();
                    }
                    
                    Container::setDefaultManager($sessionManager);
                    return $sessionManager;
                
                },
           ),
       );
    }
    
    
    public function initAcl(MvcEvent $e)
    {
        $app = $e->getTarget();
        $services = $app->getServiceManager();
        $powerManegeTable = $services->get('Crm\Table\PowerManageTable');
        $powerList = $powerManegeTable->findAll();
        if ($e->getViewModel()->acl == null) {
            $acl = new Acl;
        } else {
            $acl = $e->getViewModel()->acl;
        }
    
        foreach ($powerList as $power) {
            if (!$acl->hasResource($power['power_action'])) {
                $resource = new Resource($power['power_action']);
                $acl->addResource($resource);
            }
        }
    
        $e->getViewModel()->acl = $acl;
    }
    
    public function addUseAcl(MvcEvent $e)
    {
        $app = $e->getTarget();
        $sm = $app->getServiceManager();
    
        if ($e->getViewModel()->acl == null) {
            $acl = new Acl;
        } else {
            $acl = $e->getViewModel()->acl;
        }
    
        $auth = new AuthenticationService();
    
        if (!empty($_SESSION['account']['user_id'])) {
        //if($auth->hasIdentity()){
            $role_id = $_SESSION['account']['user_group_id'];
    
            $powerGroupTable = $sm->get('Crm\Table\PowerGroupTable');
            $has_power = $powerGroupTable->getPowerByGroupId($role_id);
            $permissions = array();
            foreach ($has_power as $power) {
                array_push($permissions,$power['power_action']);
            }
            
        } else {
            $role_name = 'guest';
            $role_id = '99999';
            $permissions = array();
        }
        
        
        if (!$acl->hasRole($role_id)) {
            $role = new Role($role_id);
            $acl->addRole($role);
        }
        foreach ($permissions as $permission) {
            $acl->allow($role_id, $permission);
        }
        return $role_id;
    }
    
    /**
     * Check acl permissions for current request
     *
     * @param MvcEvent $e
     * @return void
     */
    public function checkAcl(MvcEvent $e) {
    
        $matches    = $e->getRouteMatch();
        $role_id = $this->addUseAcl($e);
        //权限验证排除
        $controller = $matches->getParam('controller');
        if ($controller =='Crm\Controller\Login') {
            return;
        }
        //权限验证排除
        $action = $matches->getParam('action');
        if(strpos($action, 'ajax-') !== false){
            return;
        }
        
        $route = $e->getRouteMatch()->getMatchedRouteName();
        if (!$e->getViewModel()->acl->isAllowed($role_id, strtolower($route.'/'.$action))) {
             if(isset($_SERVER["HTTP_X_REQUESTED_WITH"]) && strtolower($_SERVER["HTTP_X_REQUESTED_WITH"])=="xmlhttprequest"){
                 $response=array(
                     'result' => 'false',
                     'reason' => '没有权限，请联系管理员！',
                 );
                 die(json_encode($response));
                
            }else{
//                 $matches->setParam('controller', 'Crm\Controller\Login');
//                 $matches->setParam('action', 'success');
//                 $e->setRouteMatch($matches);
                echo "<script>alert('没有权限，请联系管理员！');window.history.go(-1);;</script>";
            };
            die();
        }
        
    }
}
